using Microsoft.SqlServer.Management.Sdk.Sfc;
using Microsoft.SqlServer.Management.Smo;
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Globalization;
using System.Text;

namespace Microsoft.SqlServer.Management.SqlManagerUI.Scripting
{
using Server = Microsoft.SqlServer.Management.Smo.Server;
	internal class ScriptTableCommand : ScriptObjectCommand
	{
		private const string IfExistsCheck90 = "IF {0} EXISTS (SELECT * FROM sys.check_constraints WHERE object_id = OBJECT_ID(N'{1}') AND parent_object_id = OBJECT_ID(N'{2}'))\r\nBEGIN\r\n{3}\r\nEND\r\n";

		private const string IfExistsCheck80 = "IF {0} EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'{1}') AND type = 'C')\r\nBEGIN\r\n{3}\r\nEND\r\n";

		private const string IfExistsDefaultConstraint90 = "IF {0} EXISTS (SELECT * FROM sys.default_constraints WHERE object_id = OBJECT_ID(N'{1}') AND parent_object_id = OBJECT_ID(N'{2}'))\r\nBegin\r\n{3}\r\nEnd\r\n";

		private const string IfExistsDefaultConstraint80 = "IF {0} EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'{1}') AND type = 'D')\r\nBEGIN\r\n{3}\r\nEND\r\n";

		private TableChildObjects childObjects;

		protected bool DropData
		{
			get
			{
				return (base.ScriptActions & ScriptActions.DropData) > ScriptActions.None;
			}
		}

		protected bool ScriptDefaults
		{
			get
			{
				return (this.childObjects & TableChildObjects.DriDefaults) > TableChildObjects.None;
			}
		}

		protected bool ScriptBindings
		{
			get
			{
				return (this.childObjects & TableChildObjects.Bindings) > TableChildObjects.None;
			}
		}

		protected bool ScriptData
		{
			get
			{
				return (this.childObjects & TableChildObjects.Data) > TableChildObjects.None;
			}
		}

		protected bool Check
		{
			get
			{
				return (this.childObjects & TableChildObjects.Check) > TableChildObjects.None;
			}
		}

		protected bool ForeignKey
		{
			get
			{
				return (this.childObjects & TableChildObjects.ForeignKey) > TableChildObjects.None;
			}
		}

		protected bool FullTextIndex
		{
			get
			{
				return (this.childObjects & TableChildObjects.FullTextIndex) > TableChildObjects.None;
			}
		}

		public ScriptTableCommand(Server server, ObjectScriptedHandler scriptTarget, ScriptActions scriptAction, TableChildObjects childObjects) : base(server, scriptTarget, scriptAction)
		{
			this.childObjects = childObjects;
		}

		public override void Script(Urn objectToScript, ScriptingOptions scriptOptions)
		{
			Table table = this.GetTable(objectToScript);
			foreach (Column column in table.Columns)
			{
				if (scriptOptions.TargetServerVersion == SqlServerVersion.Version80 && NonSupportedCollation.CollationsIn2005NotIn2000().Contains(column.Collation))
				{
					throw new NonSupportedCollationException(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.ERROR_NonSupportedCollation, new object[]
					{
						column.Name,
						column.Collation
					}));
				}
			}
			if (scriptOptions.TargetServerVersion == SqlServerVersion.Version80)
			{
				foreach (Index index in table.Indexes)
				{
					if (index.IndexKeyType == IndexKeyType.DriUniqueKey && (index.IgnoreDuplicateKeys || index.PadIndex))
					{
						index.IndexKeyType = IndexKeyType.None;
					}
					else if (index.IndexKeyType == IndexKeyType.DriPrimaryKey)
					{
						index.PadIndex = false;
					}
				}
			}
			base.Script(objectToScript, scriptOptions);
			this.ScriptRuleBindings(objectToScript, scriptOptions);
			this.ScriptDropData(objectToScript, scriptOptions);
			this.ScriptTableData(objectToScript, scriptOptions);
			this.ScriptForeignKeys(objectToScript, scriptOptions);
			this.ScriptCheckConstraints(objectToScript, scriptOptions);
			this.ScriptDefaultConstraints(objectToScript, scriptOptions);
		}

		protected override void ScriptCreate(SqlSmoObject smoObject, ScriptingOptions options, ObjectScriptedHandler scriptTargetHandler)
		{
			if (smoObject is DefaultConstraint && options.IncludeIfNotExists)
			{
				StringCollection scriptEmbeddedInIfExists = ScriptTableCommand.GetScriptEmbeddedInIfExists(smoObject, options, "ScriptCreateInternal", "Not");
				scriptTargetHandler(base.GetObjectInfo(smoObject), scriptEmbeddedInIfExists, ScriptActions.Create);
				return;
			}
			if (smoObject is Table)
			{
				bool flag = false;
				Table table = (Table)smoObject;
				foreach (Index index in table.Indexes)
				{
					foreach (IndexedColumn indexedColumn in index.IndexedColumns)
					{
						if (indexedColumn.IsComputed)
						{
							flag = true;
							break;
						}
					}
					if (flag)
					{
						break;
					}
				}
				StringCollection stringCollection = new StringCollection();
				if (flag)
				{
					stringCollection.Add("SET ARITHABORT ON");
					stringCollection.Add("SET CONCAT_NULL_YIELDS_NULL ON");
					stringCollection.Add("SET ANSI_NULLS ON");
					stringCollection.Add("SET ANSI_PADDING ON");
					stringCollection.Add("SET ANSI_WARNINGS ON");
					stringCollection.Add("SET NUMERIC_ROUNDABORT OFF");
				}
				ReflectionUtilities.InvokeMethod(smoObject, "ScriptCreateInternal", new object[]
				{
					stringCollection,
					options
				});
				if (this.FullTextIndex)
				{
					FullTextIndex fullTextIndex = table.FullTextIndex;
					if (fullTextIndex != null)
					{
						ReflectionUtilities.InvokeMethod(fullTextIndex, "ScriptCreateInternal", new object[]
						{
							stringCollection,
							options
						});
					}
				}
				scriptTargetHandler(new Microsoft.SqlServer.Management.SqlManagerUI.ObjectInfo(table.Name, smoObject.Urn, table.Schema), stringCollection, ScriptActions.Create);
				return;
			}
			base.ScriptCreate(smoObject, options, scriptTargetHandler);
		}

		protected override void ScriptDrop(SqlSmoObject smoObject, ScriptingOptions options, ObjectScriptedHandler scriptTarget)
		{
			if ((smoObject is Check || smoObject is DefaultConstraint) && options.IncludeIfNotExists)
			{
				StringCollection scriptEmbeddedInIfExists = ScriptTableCommand.GetScriptEmbeddedInIfExists(smoObject, options, "ScriptDropInternal", "");
				scriptTarget(base.GetObjectInfo(smoObject), scriptEmbeddedInIfExists, ScriptActions.Drop);
				return;
			}
			base.ScriptDrop(smoObject, options, scriptTarget);
		}

		private static StringCollection GetScriptEmbeddedInIfExists(SqlSmoObject smoObject, ScriptingOptions options, string methodName, string qualifier)
		{
			StringBuilder scriptForMethod = ScriptTableCommand.GetScriptForMethod(methodName, smoObject, options);
			bool flag = options.TargetServerVersion == SqlServerVersion.Version80;
			string format;
			string name;
			Table table;
			if (smoObject is Check)
			{
				format = (flag ? "IF {0} EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'{1}') AND type = 'C')\r\nBEGIN\r\n{3}\r\nEND\r\n" : "IF {0} EXISTS (SELECT * FROM sys.check_constraints WHERE object_id = OBJECT_ID(N'{1}') AND parent_object_id = OBJECT_ID(N'{2}'))\r\nBEGIN\r\n{3}\r\nEND\r\n");
				Check check = (Check)smoObject;
				name = check.Name;
				table = (Table)check.Parent;
			}
			else
			{
				if (!(smoObject is DefaultConstraint))
				{
					return new StringCollection
					{
						scriptForMethod.ToString()
					};
				}
				format = (flag ? "IF {0} EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'{1}') AND type = 'D')\r\nBEGIN\r\n{3}\r\nEND\r\n" : "IF {0} EXISTS (SELECT * FROM sys.default_constraints WHERE object_id = OBJECT_ID(N'{1}') AND parent_object_id = OBJECT_ID(N'{2}'))\r\nBegin\r\n{3}\r\nEnd\r\n");
				DefaultConstraint defaultConstraint = (DefaultConstraint)smoObject;
				name = defaultConstraint.Name;
				table = (Table)defaultConstraint.Parent.Parent;
			}
			string value = string.Format(CultureInfo.InvariantCulture, format, new object[]
			{
				qualifier,
				ReflectionUtilities.EscapeString(ScriptTableCommand.GetQualfiedName(options, name, table), '\''),
				ReflectionUtilities.EscapeString(ScriptTableCommand.GetTableName(options, table), '\''),
				scriptForMethod.ToString()
			});
			return new StringCollection
			{
				value
			};
		}

		private static StringBuilder GetScriptForMethod(string methodName, SqlSmoObject smoObject, ScriptingOptions options)
		{
			StringCollection stringCollection = new StringCollection();
			ReflectionUtilities.InvokeMethod(smoObject, methodName, new object[]
			{
				stringCollection,
				options
			});
			StringBuilder stringBuilder = new StringBuilder();
			foreach (string current in stringCollection)
			{
				stringBuilder.AppendLine(current);
			}
			return stringBuilder;
		}

		private static string GetQualfiedName(ScriptingOptions options, string objectName, Table parent)
		{
			string result = string.Empty;
			if (options.IncludeIfNotExists)
			{
				result = string.Format(CultureInfo.InvariantCulture, "[{0}].[{1}]", new object[]
				{
					parent.Schema,
					objectName
				});
			}
			else
			{
				result = string.Format(CultureInfo.InvariantCulture, "[{0}]", new object[]
				{
					objectName
				});
			}
			return result;
		}

		protected virtual Table GetTable(Urn sourceObject)
		{
			return (Table)this.GetSqlSmoObject(sourceObject);
		}

		private void ScriptDropData(Urn objectToScript, ScriptingOptions scriptOptions)
		{
			if (this.DropData)
			{
				Table table = this.GetTable(objectToScript);
				StringCollection stringCollection = new StringCollection();
				stringCollection.Add(string.Format(CultureInfo.InvariantCulture, "DELETE FROM {0}", new object[]
				{
					ScriptTableCommand.GetTableName(scriptOptions, table)
				}));
				base.ScriptTarget(new Microsoft.SqlServer.Management.SqlManagerUI.ObjectInfo(table.Name, table.Urn, table.Schema), stringCollection, ScriptActions.DropData);
			}
		}

		private void ScriptRuleBindings(Urn objectToScript, ScriptingOptions scriptOptions)
		{
			if (this.ScriptBindings)
			{
				scriptOptions.Bindings = true;
				StringCollection stringCollection = new StringCollection();
				Table table = this.GetTable(objectToScript);
				foreach (Column obj in table.Columns)
				{
					StringCollection stringCollection2 = new StringCollection();
					ReflectionUtilities.InvokeMethod(obj, "ScriptDefaultAndRuleBinding", new object[]
					{
						stringCollection2,
						scriptOptions
					});
					foreach (string current in stringCollection2)
					{
						stringCollection.Add(current);
					}
				}
				if (stringCollection.Count > 0)
				{
					base.ScriptTarget(new Microsoft.SqlServer.Management.SqlManagerUI.ObjectInfo(table.Name, table.Urn, table.Schema), stringCollection, ScriptActions.Bindings);
				}
			}
		}

		private void ScriptTableData(Urn objectToScript, ScriptingOptions scriptOptions)
		{
			if (this.ScriptData)
			{
				Table table = this.GetTable(objectToScript);
				IEnumerable script = ReflectionUtilities.InvokeMethod(table, "ScriptDataInternal", new object[]
				{
					scriptOptions
				}) as IEnumerable;
				TableDataWrapper script2 = new TableDataWrapper(script, table, scriptOptions);
				base.ScriptTarget(new Microsoft.SqlServer.Management.SqlManagerUI.ObjectInfo(table.Name, table.Urn, table.Schema), script2, ScriptActions.Data);
			}
		}

		public static string GetTableName(ScriptingOptions scriptOptions, Table table)
		{
			string result = string.Empty;
			if (scriptOptions.SchemaQualify)
			{
				result = string.Format(CultureInfo.InvariantCulture, "[{0}].[{1}]", new object[]
				{
					table.Schema,
					table.Name
				});
			}
			else
			{
				result = string.Format(CultureInfo.InvariantCulture, "[{0}]", new object[]
				{
					table.Name
				});
			}
			return result;
		}

		protected virtual void ScriptCheckConstraints(Urn objectToScript, ScriptingOptions scriptOptions)
		{
			if (this.Check)
			{
				scriptOptions.DriChecks = true;
				this.ScriptCollection(this.GetTable(objectToScript).Checks, scriptOptions);
			}
		}

		protected virtual void ScriptDefaultConstraints(Urn objectToScript, ScriptingOptions scriptOptions)
		{
			if (this.ScriptDefaults)
			{
				scriptOptions.DriDefaults = true;
				Table table = this.GetTable(objectToScript);
				foreach (Column column in table.Columns)
				{
					if (column.DefaultConstraint != null)
					{
						base.ScriptSqlSmoObject(column.DefaultConstraint, scriptOptions);
					}
				}
			}
		}

		protected virtual void ScriptForeignKeys(Urn objectToScript, ScriptingOptions scriptOptions)
		{
			if (this.ForeignKey)
			{
				scriptOptions.DriForeignKeys = true;
				this.ScriptCollection(this.GetTable(objectToScript).ForeignKeys, scriptOptions);
			}
		}

		protected void ScriptCollection(ICollection collection, ScriptingOptions scriptOptions)
		{
			if (collection != null)
			{
				foreach (SqlSmoObject smoObject in collection)
				{
					base.ScriptSqlSmoObject(smoObject, scriptOptions);
				}
			}
		}
	}
}
